package com.ys.service.account.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.ys.entity.sys.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ys.dto.AddDto;
import com.ys.dto.EditDto;
import com.ys.entity.account.TcwNeedPayAccount;
import com.ys.entity.account.TcwNeedPayAccountPay;
import com.ys.entity.account.TcwNeedPayAccountPayItem;
import com.ys.entity.account.TcwNeedPayLedgerDetail;
import com.ys.entity.business.TbBaseInfo;
import com.ys.entity.finance.TcwAccountCountForCompany;
import com.ys.entity.finance.TcwPartnerBankInfo;
import com.ys.entity.flow.YspModel;
import com.ys.entity.hr.ThrOperateCompanyApply;
import com.ys.enume.finance.TcwFinancialTransactionFlowEnum;
import com.ys.enume.flow.FlowEnum;
import com.ys.enume.flow.YsProcInstEnum;
import com.ys.mapper.account.AccountMapper;
import com.ys.mapper.account.TcwNeedPayAccountPayItemMapper;
import com.ys.mapper.account.TcwNeedPayAccountPayMapper;
import com.ys.service.account.TcwNeedPayAccountPayService;
import com.ys.service.business.TcwAccountDetailedForCompanyService;
import com.ys.service.finance.TcwFinancialTransactionFlowService;
import com.ys.service.flow.YspTaskService;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.Flow;
import com.ys.vo.R;

@Service("tcwNeedPayAccountPayService")
public class TcwNeedPayAccountPayServiceImpl implements TcwNeedPayAccountPayService {
	@Autowired
	private AccountMapper accountMapper;

	@Autowired
	private TcwNeedPayAccountPayMapper tcwNeedPayAccountPayMapper;
	@Autowired
	private TcwNeedPayAccountPayItemMapper tcwNeedPayAccountPayItemMapper;
	
	@Autowired
	private YspTaskService yspTaskService;
	@Autowired
	private TcwAccountDetailedForCompanyService tcwAccountDetailedForCompanyService;

	@Autowired
	private TcwFinancialTransactionFlowService tcwFinancialTransactionFlowService;

	/*
	 * 新增页
	 */
	@Override
	public R add(String bid, String needPayAccountCode, String companyBankInfoVid, String remark, String detailArr, Long menuId,int payStatus) throws Exception {

		if (bid == null || bid.length() == 0) {
			return R.error("单号不能为空");
		} else if(new TcwNeedPayAccountPay().setBid(bid).count() > 0) {
			return R.error("单号已存在");
		}
		
		if (needPayAccountCode == null || needPayAccountCode.length() == 0) {
			return R.error("应付账户编码不能为空");
		}
		
		if (companyBankInfoVid == null || companyBankInfoVid.length() == 0) {
			return R.error("公司账户编码不能为空");
		}
		
		/*
		 *  验证详情数据
		 */
		JSONArray detailJA = JSON.parseArray(detailArr);
		if (detailJA == null || detailJA.size() == 0) {
			return R.error("详情数据不能为空");
		}
		for (int i = 0; i < detailJA.size(); i++) {
			JSONObject detailJO = detailJA.getJSONObject(i);

			BigDecimal amount = detailJO.getBigDecimal("amount");
			if (amount == null) {
				return R.error("本次付款金额不能为空");
			} else if (amount.compareTo(BigDecimal.ZERO) < 0) {
				return R.error("本次付款金额不能为负");
			}
			Long needPayLedgerDetailId = detailJO.getLong("needPayLedgerDetailId");
			if (needPayLedgerDetailId == null) {
				return R.error("应付台账明细ID不能为空");
			}
			
			TcwNeedPayLedgerDetail tcwNeedPayLedgerDetail = new TcwNeedPayLedgerDetail().setId(needPayLedgerDetailId).queryFirst();
			BigDecimal unpayPrice = tcwNeedPayLedgerDetail.getCostPrice()
					.multiply(tcwNeedPayLedgerDetail.getQuantity())
					.subtract(tcwNeedPayLedgerDetail.getPayedPrice());
			if (amount.compareTo(unpayPrice) > 0) {
				return R.error("本次金额不得高于未付金额");
			}
		}
		
		String loginUserId = ShiroUtils.getUserId();
		TsUserChange tsUserChange = new TsUserChange().setUserId(loginUserId).setStatus(1).queryFirst();
		
		TcwNeedPayAccountPay entity = null;
		{
			Integer effectStock = FlowEnum.EffectStock.NOT_EFFECT.value;
			Long createChangeId = tsUserChange.getId();
			String annexFile = null;
			entity = TcwNeedPayAccountPay.tcwNeedPayAccountPay(bid, effectStock, createChangeId, needPayAccountCode, companyBankInfoVid, annexFile, remark, payStatus,1);
			tcwNeedPayAccountPayMapper.insert(entity);
		}
		
		// 添加明细
		for (int i = 0; i < detailJA.size(); i++) {
			JSONObject detailJO = detailJA.getJSONObject(i);
			
			String pbid = bid;
			Long needPayLedgerDetailId = detailJO.getLong("needPayLedgerDetailId");
			BigDecimal amount = detailJO.getBigDecimal("amount");
			TcwNeedPayAccountPayItem tcwNeedPayAccountPayItem = TcwNeedPayAccountPayItem.tcwNeedPayAccountPayItem(pbid, needPayLedgerDetailId, amount, 1);
			tcwNeedPayAccountPayItemMapper.insert(tcwNeedPayAccountPayItem);
		}
		
		/*
		 * 流程初始化
		 */
		YsMenu ysMenu = new YsMenu().setId(menuId).queryFirst();
		if (ysMenu.getFlowModelId().longValue() != 0L) {
			YspModel yspModel = new YspModel().setId(ysMenu.getFlowModelId()).queryFirst();
			String codeModel = yspModel.getCode();
			String createUserId = ShiroUtils.getUserId();
			yspTaskService.init(codeModel, bid, createUserId);

			TbCompanyInfo tbCompanyInfo = new TbCompanyInfo().setVid(companyBankInfoVid).queryFirst();
			yspTaskService.setOtherParams(entity.getBid(),entity.getRemark(),tbCompanyInfo!=null?tbCompanyInfo.getVname():"");
		}
		return R.ok(AddDto.gotoEdit("/web/account/tcwNeedPayAccountPay/toFlow?bid=" + bid));
	}
	
	@Override
	@Transactional
	public R edit(String bid, String needPayAccountCode, String companyBankInfoVid, String remark, String annexFile, String detailArr, Long menuId,int payStatus) throws Exception {
		
		Integer stateFlow = yspTaskService.flowState(bid);
		if (stateFlow != YsProcInstEnum.StateFlow.INIT.value) {
			return R.error("非制单中数据，无法修改");
		}
		
		// 验证是否制单人
		YsProcInst entity = new YsProcInst().setBid(bid).queryFirst();
		if (!entity.getCreateUserId().equals(ShiroUtils.getUserId())) {
			return R.error("非制单人无法修改");
		}

		if (bid == null || bid.length() == 0) {
			return R.error("单号不能为空");
		}
		
		if (needPayAccountCode == null || needPayAccountCode.length() == 0) {
			return R.error("应付账户编码不能为空");
		}
		
		if (companyBankInfoVid == null || companyBankInfoVid.length() == 0) {
			return R.error("公司账户编码不能为空");
		}
		
		/*
		 *  验证详情数据
		 */
		JSONArray detailJA = JSON.parseArray(detailArr);
		if (detailJA == null || detailJA.size() == 0) {
			return R.error("详情数据不能为空");
		}
		for (int i = 0; i < detailJA.size(); i++) {
			JSONObject detailJO = detailJA.getJSONObject(i);

			BigDecimal amount = detailJO.getBigDecimal("amount");
			if (amount == null) {
				return R.error("本次付款金额不能为空");
			} else if (amount.compareTo(BigDecimal.ZERO) < 0) {
				return R.error("本次付款金额不能为负");
			}
			Long needPayLedgerDetailId = detailJO.getLong("needPayLedgerDetailId");
			if (needPayLedgerDetailId == null) {
				return R.error("应付台账明细ID不能为空");
			}
			
			TcwNeedPayLedgerDetail tcwNeedPayLedgerDetail = new TcwNeedPayLedgerDetail().setId(needPayLedgerDetailId).queryFirst();
			BigDecimal unpayPrice = tcwNeedPayLedgerDetail.getCostPrice()
					.multiply(tcwNeedPayLedgerDetail.getQuantity())
					.subtract(tcwNeedPayLedgerDetail.getPayedPrice());
			if (amount.compareTo(unpayPrice) > 0) {
				return R.error("本次金额不得高于未付金额");
			}
		}
		
		TcwNeedPayAccountPay tcwNeedPayAccountPay = new TcwNeedPayAccountPay().setBid(bid).queryFirst();
		tcwNeedPayAccountPay
			.setPayStatus(payStatus)
			.setCompanyBankInfoVid(companyBankInfoVid)
			.setAnnexFile(annexFile)
			.setNeedPayAccountCode(needPayAccountCode);
		tcwNeedPayAccountPayMapper.update(tcwNeedPayAccountPay);
			
		
		// 删除旧的详情数据
		accountMapper.deleteBatchTcwNeedPayAccountPayItemByPbid(bid);
		
		// 添加明细
		for (int i = 0; i < detailJA.size(); i++) {
			JSONObject detailJO = detailJA.getJSONObject(i);
			
			String pbid = bid;
			Long needPayLedgerDetailId = detailJO.getLong("needPayLedgerDetailId");
			BigDecimal amount = detailJO.getBigDecimal("amount");
			TcwNeedPayAccountPayItem tcwNeedPayAccountPayItem = TcwNeedPayAccountPayItem.tcwNeedPayAccountPayItem(pbid, needPayLedgerDetailId, amount, 1);
			tcwNeedPayAccountPayItemMapper.insert(tcwNeedPayAccountPayItem);
		}

		TbCompanyInfo tbCompanyInfo = new TbCompanyInfo().setVid(companyBankInfoVid).queryFirst();
		yspTaskService.setOtherParams(entity.getBid(),tcwNeedPayAccountPay.getRemark(),tbCompanyInfo!=null?tbCompanyInfo.getVname():"");
		
		return R.ok(EditDto.reloadPage("/web/account/tcwNeedPayAccountPay/toFlow?bid=" + bid));
	}

	@Override
	@Transactional
	public R deleteTrue(Long id) throws Exception {
		if (id == null) {
			return R.error("ID不能为空");
		}
		
		TcwNeedPayAccountPay entity = new TcwNeedPayAccountPay().setId(id).queryFirst();
		if (entity.getEffectStock() == FlowEnum.EffectStock.EFFECTED.value) {
			return R.error("已生效数据无法删除");
		}
		// 验证是否制单人
		String loginUserId = ShiroUtils.getUserId();
		TsUserChange tsUserChange = new TsUserChange().setId(entity.getCreateChangeId()).queryFirst();
		
		if (!tsUserChange.getUserId().equals(loginUserId)) {
			return R.error("非制单人，无法删除");
		}
		
		// 删除主数据
		tcwNeedPayAccountPayMapper.deleteTrue(id);
		
		// 删除子数据
		accountMapper.deleteBatchTcwNeedPayAccountPayItemByPbid(entity.getBid());
		
		yspTaskService.flowDelete(entity.getBid(), loginUserId);
		return R.ok();
	}

	@Override
	@Transactional
	public R flowPass(String bid, String loginUserId) throws Exception {
		
		// 流转前验证每一条明细下的账户余额
		YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();
		if (ysProcInst.getStateFlow() == YsProcInstEnum.StateFlow.INIT.value) {
			BigDecimal amountAll  = new TcwNeedPayAccountPayItem().setPbid(bid).setFields("ISNULL(SUM(A.Amount),0)").sumDecimal();

			TcwNeedPayAccountPay entity = new TcwNeedPayAccountPay().setBid(bid).queryFirst();
			TcwNeedPayAccount tcwNeedPayAccount = new TcwNeedPayAccount().setCode(entity.getNeedPayAccountCode()).queryFirst();
			TcwAccountCountForCompany tcwAccountCountForCompany = new TcwAccountCountForCompany().setVGsBm(tcwNeedPayAccount.getVgsbm()).queryFirst();
//			if (tcwAccountCountForCompany.getFJe().compareTo(amountAll) < 0) {
//				return R.error("【" + tcwNeedPayAccount.getVgsbm() + "】账户余额不足");
//			}
		}
		
		try {
			Flow f = yspTaskService.flowPass(bid, loginUserId);
			if (f.getCode() == Flow.Code.FAILED.value) {
				return R.error(f.getMsg());
			} else {
				
				if (f.getState() == Flow.State.FINISH.value) {
					flowFinish(bid);
				}
				return R.ok();
			}
		} catch (Exception e) {
			e.printStackTrace();
			return R.error("服务器正在开小差，请联系客服");
		}
	}

	@Override
	public R flowRefuse(String bid, String reason, String loginUserId) throws Exception {
		
		R r = yspTaskService.flowRefuse(bid, reason, loginUserId);
		return r;
	}

	@Override
	public void flowFinish(String bid) throws Exception {

		TcwNeedPayAccountPay entity = new TcwNeedPayAccountPay().setBid(bid).queryFirst();
		
		YsProcInst ysProcInst = new YsProcInst().setBid(entity.getBid()).queryFirst();
		if (ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.FINISH.value) {
			return;
		}




		entity.setEffectStock(FlowEnum.EffectStock.EFFECTED.value);
		tcwNeedPayAccountPayMapper.update(entity);

		TbCompanyBankInfo tbCompanyBankInfo = new TbCompanyBankInfo().setVid(entity.getCompanyBankInfoVid()).queryFirst();
		if(tbCompanyBankInfo==null || tbCompanyBankInfo.getId()==null){
			throw new IllegalArgumentException("未查询到对公账户管理表信息");
		}

		/*
		 *  更新台账的已付金额和未付金额
		 *  计算应付总额
		 */
		List<TcwNeedPayAccountPayItem> listDetail = new TcwNeedPayAccountPayItem().setPbid(bid).queryList();
		Date now = new Date();
		
		TcwNeedPayAccount tcwNeedPayAccount = new TcwNeedPayAccount().setCode(entity.getNeedPayAccountCode()).queryFirst();
		TcwPartnerBankInfo tcwPartnerBankInfo = new TcwPartnerBankInfo().setVid(tcwNeedPayAccount.getPartnerBankInfoVid()).queryFirst();
		for (int i = 0; i < listDetail.size(); i++) {
			TcwNeedPayAccountPayItem detail = listDetail.get(i);
			// 更新台账的已付金额和未付金额
			accountMapper.updateTcwNeedPayLedgerDetailOfAmount(detail.getNeedPayLedgerDetailId());
			
			TcwNeedPayLedgerDetail tcwNeedPayLedgerDetail = new TcwNeedPayLedgerDetail().setId(detail.getNeedPayLedgerDetailId()).queryFirst();
			// 付款方账户变动
			String vgsbm = tcwNeedPayAccount.getVgsbm();
			ThrOperateCompanyApply thrOperateCompanyApply = new ThrOperateCompanyApply().setVgsbm(vgsbm).queryFirst();
			String vgsjc = thrOperateCompanyApply.getVgsjc();
			String vgsbmp = tcwPartnerBankInfo.getPartnerId();
			String vgsjcp = tcwPartnerBankInfo.getPartnerName();
			String vjylx = tcwNeedPayLedgerDetail.getVjylx();
			BigDecimal fje = detail.getAmount().negate();
			Date djysj = now;
			Date dshsj = now;
			String vbz = "应付账户支付单," + entity.getBid() + ",金额," + detail.getAmount();
			Date writeTime = now;

			//PayStatus 状态为1时，才产生流水
			if(entity.getPayStatus()==1){
				//业务流水
				tcwAccountDetailedForCompanyService.addTcwAccountDetailedForCompanyWithJc(vgsbm, vgsjc, vgsbmp, vgsjcp, vjylx, fje, djysj, dshsj, vbz,entity.getBid(), writeTime);

				//获取业务交易类型信息
				String transactionTypeStr = tcwNeedPayLedgerDetail.getVjylx();
				TbBaseInfo transactionTypeItem = tcwFinancialTransactionFlowService.getTransactionType(transactionTypeStr);

				//财务交易流水
				if(transactionTypeItem!=null && transactionTypeItem.getId()!=null){

					R res = tcwFinancialTransactionFlowService.add(true,
							tbCompanyBankInfo.getId(), transactionTypeItem.getBid(),
							tcwPartnerBankInfo.getVyhzhmc(),tcwPartnerBankInfo.getVkhh(), tcwPartnerBankInfo.getVyhzh(),
							detail.getAmount().negate(),
							entity.getCreateTime(),now,new Date(),"应付账户支付"+entity.getBid()+entity.getRemark(),
							TcwFinancialTransactionFlowEnum.FromType.TCW_NeedPayAccountPayItem.value,entity.getId());
					if(res.getCode().equals( R.Code.FAILED.value)){
						throw new IllegalArgumentException(res.getMsg());
					}
				}
			}


		}
		
		accountMapper.updateTcwNeedPayLedgerDetailOfState();
		
	}

	@Override
	@Transactional
	public List<Map<String, Object>> getItemList(String bid) throws Exception{
		// 子列表配置信息
		List<Map<String, Object>> sonlist = new TcwNeedPayAccountPayItem()
				.setPbid(bid)
				.addLeftJoin("TCW_NeedPayAccountPay B on B.Bid = A.Pbid")

				.addLeftJoin("TCW_NeedPayLedgerDetail C on C.Id = A.NeedPayLedgerDetailId")
				.addField("C.NeedPayTypeCode needPayTypeCode")
				.addField("C.DetailName detailName")
				.addField("C.CostPrice costPrice")
				.addField("C.Quantity quantity")
				.addField("(C.CostPrice + C.ServicePrice) * C.Quantity totalPrice")
				.addField("C.ServicePrice servicePrice")
				.addField("C.PayedPrice payedPrice")
				.addField("(C.CostPrice * C.Quantity - C.PayedPrice) unpayPrice")
				.addField("C.Remark remark")
				.addField("C.Vjylx vjylx")
				.addField("C.ProxyPrice proxyPrice")

				.addLeftJoin("TB_NeedPayType C1 on C1.Code = C.NeedPayTypeCode")
				.addField("C1.Name needPayTypeName")

				.addLeftJoin("THR_OperateCompanyApply C2 on C2.Vgsbm = C.Vgsbm")
				.addField("C2.Vgsbm vgsbm")
				.addField("C2.Vgsjc vgsjc")

				.queryMap();
		return sonlist;
	}

	@Override
	@Transactional
	public Map<String,Object> getExtraParam( String bid) throws Exception{
		Map<String, Object> extraParam = new TcwNeedPayAccountPay()
				.setBid(bid)


				.addLeftJoin("TCW_NeedPayAccount B1 on B1.Code = A.NeedPayAccountCode")
				.addField("B1.Name needPayAccountName")
				.addField("B1.PartnerBankInfoVid partnerBankInfoVid")

				.addLeftJoin("TB_CompanyInfo B2 on B2.Vid = B1.CompanyVid")
				.addField("B2.Vname companyVname")

				.addLeftJoin("TCW_PartnerBankInfo B3 on B3.Vid = B1.PartnerBankInfoVid")
				.addField("B3.Vyhzhmc partnerBankInfoVyhzhmc")
				.addField("B3.Vkhh partnerBankInfoVkhh")
				.addField("B3.Vyhzh partnerBankInfoVyhzh")
				.addField("B3.PartnerId partnerId")
				.addField("B3.PartnerName partnerName")

				.addLeftJoin("THR_OperateCompanyApply B4 on B4.Vgsbm = B1.Vgsbm")
				.addField("B4.Vgsbm vgsbm")
				.addField("B4.Vgsjc vgsjc")

				.addLeftJoin("TCW_AccountCountForCompany B5 on B5.Vgsbm = B4.Vgsbm")
				.addField("B5.Fje fje")

				.addLeftJoin("TB_CompanyBankInfo D on D.Vid = A.CompanyBankInfoVid")
				.addField("D.Vyhzhmc companyBankInfoVyhzhmc")
				.addField("D.Vyhzh companyBankInfoVyhzh")
				.addField("D.Vkhh companyBankInfoVkhh")

				.addLeftJoin("YS_ProcInst F on F.Bid = A.Bid")
				.addField("F.UpdateTime auditTime")

				//.clearFieldsSource()
				.queryFirstMap();

		// 本次支付总额
		BigDecimal amountAll = new TcwNeedPayAccountPayItem().setPbid(bid).setFields("ISNULL(SUM(A.Amount),0)").sumDecimal();

		// 总计金额
		BigDecimal totalPriceAll = new TcwNeedPayAccountPayItem()
				.setPbid(bid)
				.addLeftJoin("TCW_NeedPayLedgerDetail B on B.Id = A.NeedPayLedgerDetailId")
				.setPbid(bid).setFields("ISNULL(SUM(B.CostPrice * B.Quantity),0)").sumDecimal();

		// 已付金额
		BigDecimal payedPrice = new TcwNeedPayAccountPayItem()
				.setPbid(bid)
				.addLeftJoin("TCW_NeedPayLedgerDetail B on B.Id = A.NeedPayLedgerDetailId")
				.setPbid(bid).setFields("ISNULL(SUM(B.PayedPrice),0)").sumDecimal();
		extraParam.put("totalPriceAll", totalPriceAll);
		extraParam.put("payedPrice", payedPrice);
		extraParam.put("unpayPrice", totalPriceAll.subtract(payedPrice));
		extraParam.put("amountAll", amountAll);

		return extraParam;
	}


}
